#include "Block.h"

using namespace std;

#include "Environment.h"
#include "Player.h"
extern Environment env;

extern Block* allocateBlockByID(int x, int y, int ID);

Block::Block(int x, int y, int ID, bool transparent) :
        transparent(transparent),
        Item(ID),
        isBeingHit(false),
        dmg(0.0f),
        x(x), y(y) {
    lastHit = -1.0f;
}

void Block::draw() {
    if (ID == AIR) return;

    ofEnableAlphaBlending();
    ofDisableSmoothing();

    glEnable(GL_ALPHA);
    ofSetColor(0xFFFFFF);
    //glBindTexture(GL_TEXTURE_2D, Resources::get()->textureByID(this->ID));
    glEnable(GL_TEXTURE_2D);

    ofPushMatrix();
    ofTranslate(x, y);
    ofScale(1.01f, 1.01f);
    //glCallList(Resources::get()->list(SQUARE1X1));
    glCallList(Resources::get()->terrainListByID(ID));
    ofPopMatrix();

    glDisable(GL_TEXTURE_2D);

    ofDisableAlphaBlending();
}

bool Block::destroy(Item *tool) {
    if (transparent) return false;
    float thisHit = ofGetElapsedTimef();

    if (!isBeingHit) {
        isBeingHit = true;
        lastHit = thisHit;
        return false;
    }

    float dmgRate;

    if (dmgRates.find(tool->ID) != dmgRates.end())
        dmgRate = dmgRates[tool->ID];
    else
        dmgRate = 1/2.0f;

    dmgRate *= (thisHit - lastHit);

    dmg += dmgRate;

    if (dmg > 1.0f) {
        releaseBlock();
        return true;
    }

    lastHit = thisHit;
    isBeingHit = true;
    return false;
}

void Block::activate(BlockActivationEvent e) {
    if (e.side == ' ') return;

    ofPoint offset;
    offset.set(((e.side == 'E') || (e.side == 'e') ? -1 :
                (e.side == 'W') || (e.side == 'w') ?  1 : 0),
               ((e.side == 'U') || (e.side == 'u') ? -1 :
                (e.side == 'D') || (e.side == 'd') ?  1 : 0));

    if (e.tool > 0) {
        if (e.sender->deleteItemsFromInventory()) {
            env.placeBlockAtCoord(x+offset.x, y+offset.y,
                allocateBlockByID(x+offset.x, y+offset.y, e.tool));
        }
    }
}

void Block::stopHitting() {
    dmg = 0.0f;
    lastHit = -1.0f;
    isBeingHit = false;
}

void Block::releaseBlock() {
    releaseBlockByID(this->ID);
}

void Block::releaseBlockByID(int ID) {
    for (int i = 0; i < 20; ++i) {
        env.particles.push_back(new Particle(ofPoint(x+.5,y+.5), ofPoint(ofRandomf()/5.0f, ofRandomuf()/5.0f), 1.0f+ofRandomf()/3));
        env.particles.back()->setColor(getColor());
    }
    env.itemParticles.push_back(new ItemParticle(ofPoint(x+.5,y+.5), ofPoint(ofRandomf()/5.0f, ofRandomuf()/5.0f), ID));
}

float Block::damageValue() {
    return dmg;
}

int Block::getColor() {
    switch (ID) {
        case STONE:
            return BLOCKCOLOR_STONE;
        case DIRT:
            return BLOCKCOLOR_DIRT;
        case BEDROCK:
            return BLOCKCOLOR_BEDROCK;
        default:
            return 0x0000FF;
    }
}
